<?php

declare (strict_types = 1);

namespace app\common\service\file;

use app\common\repository\file\FileUploadsRepository;
use app\common\service\BaseService;
use think\exception\ValidateException;
use think\facade\Filesystem;
use think\facade\Request;

class FileUploadsService extends BaseService
{
    public function __construct(FileUploadsRepository $repository)
    {
        $this->repository = $repository;
    }

    /**
     * 获取列表
     *
     * @param array $where
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     */
    public function getList(array $where = []): array
    {
        [$page, $pageSize] = $this->getPaginationParams();
        return $this->repository->paginate($where, ['id' => 'desc'], $page, $pageSize);
    }

    /**
     * 重命名
     *
     * @param $data
     * @param $where
     * @return bool|int
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function update($data, $where): bool|int
    {
        return $this->repository->update($data, $where);
    }

    /**
     * 更换分类
     *
     * @param $data
     * @return bool|int
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function move($data): bool|int
    {
        return $this->repository->update(['cid' => $data['cid']], [
            ['id', 'in', $data['ids']]
        ]);
    }

    /**
     * 删除文件
     *
     * @param $where
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function delete($where): bool
    {
        $res = $this->repository->getByWhere([
            ['id', 'in', $where]
        ]);
        foreach ($res as $file) {
            // 获取文件的完整路径
            $publicPath = root_path('public') . DIRECTORY_SEPARATOR . 'storage' . DIRECTORY_SEPARATOR;
            $relativeFilePath = $file['file_path']; // 例如：image/20252456/asd.png

            // 组合完整路径
            $fullFilePath = realpath($publicPath . $relativeFilePath);

            // 确保文件存在且位于 public/storage 目录下以防止目录遍历攻击
            if (is_string($fullFilePath) && file_exists($fullFilePath)) {
                // 尝试删除文件
                unlink($fullFilePath);
            }
        }
        return $this->repository->delete($where);
    }

    /**
     * 文件上传
     *
     * @return array
     * @throws \Exception
     */
    public function upload(): array
    {
        $files = Request::file('files');
        $cid = Request::param('cid');
        $upload_config = get_config('upload_config'); // 上传配置

        // 验证规则
        $validate = [
            'files' => [
                'fileExt'  => explode(',', $upload_config['upload_file_ext']),
//                'fileMime' => explode(',', $upload_config['upload_file_mime']),
                'fileSize' => intval($upload_config['upload_file_size']) * 1024 * 1024,
            ]
        ];

        // 检查是否为字符串 'null' 或者 null 或者 空字符串
        if ($cid === 'null' || $cid === null || $cid === '' || $cid === 'undefined') {
            $cid = 0;
        }
        try {
            validate($validate)->check(['files' => $files]);
        }catch (ValidateException $e){
            throw new ValidateException($e->getMessage());
        }

        $save_name = [];

        foreach ($files as $file) {
            // 获取文件的MIME类型
            $mimeType = $file->getOriginalMime();
            // 判断文件类型
            if (str_starts_with($mimeType, 'image/')) {
                // 图片
                $file_type = 'image';
            } elseif (str_starts_with($mimeType, 'video/')) {
                // 视频
                $file_type = 'video';
            } elseif (str_starts_with($mimeType, 'audio/')) {
                // 音频
                $file_type = 'audio';
            } else {
                // 其他文件类型
                $file_type = 'document';
            }

            // 保存文件到public/storage/image目录
            $file_path = Filesystem::disk('public')->putFile($file_type, $file);

            // 使用str_replace函数将反斜杠替换为正斜杠
            $file_path = str_replace('\\', '/', $file_path);


            // 拼接图片完整url
            $scheme = Request::scheme();
            $host = Request::host();
            $file_url = "{$scheme}://{$host}/storage/{$file_path}";

            $save_name[] = $file_url;

            // 获取文件名部分
            $stored_name = basename($file_path);

            // 保存到数据库
            $this->repository->save([
                'hash'          => $file->hash('md5'),
                'original_name' => $file->getOriginalName(),
                'stored_name'   => $stored_name,
                'file_path'     => $file_path,
                'file_type'     => $file_type,
                'file_size'     => $file->getSize(),
                'file_url'      => $file_url,
                'mime_type'     => $file->getMime(),
                'cid'           => $cid,
            ]);
        }
        return $save_name;
    }
}